// 类写法

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig, AxiosError } from 'axios'

class Request {
  private instance: AxiosInstance
  private readonly baseConfig: AxiosRequestConfig = {
    baseURL: 'http://127.0.0.1:4523/m1/5702810-5383946-default', // 设置基础URL
    timeout: 5000 // 超时时间
    // headers: {
    //   'Content-Type': 'application/json;charset=UTF-8'
    // }
  }

  // config 除了基础的方式之外hiatus可以进行额外的配置
  constructor(config?: AxiosRequestConfig) {
    // 实例化
    this.instance = axios.create(Object.assign(this.baseConfig, config))
    // 请求拦截器
    this.instance.interceptors.request.use(
      // 配置文件添加token 可写可不写 因为ts可以根据返回值进行类型推断
      (config: InternalAxiosRequestConfig): InternalAxiosRequestConfig => {
        const token = localStorage.getItem('token')
        if (token) {
          config.headers.Authorization = `Bearer ${token}`
        }
        return config
      },
      (error: AxiosError) => {
        // 对请求错误做些什么
        console.error('请求错误:', error)
        return Promise.reject(error)
      }
    )
    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        return response
      },
      (error: AxiosError) => {
        // 对请求错误做些什么
        console.error('请求错误:', error)
        return Promise.reject(error)
      }
    )
  }

  public getData = async <T = any>(url: string, data: { data: object; signal?: AbortSignal }): Promise<T> => {
    const result = await this.instance.get<T>(url, { params: data.data, signal: data.signal })
    return result.data
  }
  public postData = async <T = any>(url: string, data: { data: object; signal?: AbortSignal }): Promise<T> => {
    const result = await this.instance.post<T>(url, data.data, {
      signal: data.signal
    })
    return result.data
  }
  public putData = async <T = any>(url: string, data: { data: object; signal?: AbortSignal }): Promise<T> => {
    const result = await this.instance.put<T>(url, data.data, {
      signal: data.signal
    })
    return result.data
  }

  public deleteData = async <T = any>(url: string, data: { params?: object; signal?: AbortSignal }): Promise<T> => {
    const result = await this.instance.delete<T>(url, {
      params: data.params,
      signal: data.signal
    })
    return result.data
  }
}

// 单例模式
export const { getData, postData, putData, deleteData } = new Request()
